/*
 * @Author: crissu 13750782397@163.com
 * @Date: 2024-06-04 01:13:35
 * @LastEditors: crissu 13750782397@163.com
 * @LastEditTime: 2024-06-04 01:19:26
 * @FilePath: /try_concurrence/Patterns/ORDone.go
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
package patterns

import (
	"fmt"
	"time"
)

// 完成某件事有一种方式可以封装冗长的代码,这种方式可以通过使用for循环/select语句来检查通道是否已经关闭,同时也可以避免goroutine的泄露。
// 下面的代码可以用一个闭包来替代,从而封装掉这种冗长的代码。
func TryOrDone() {
	orDone := func(done, c <-chan interface{}) <-chan interface{} {
		valStream := make(chan interface{})
		go func() {
			defer close(valStream)
			for {
				select {
				case <-done:
					fmt.Println("finish")
					return
				case v, ok := <-c:
					if !ok {
						return
					}
					select {
					case valStream <- v:
					case <-done:
					}
				}
			}
		}()
		return valStream
	}
	myChan := make(chan interface{})
	done := make(chan interface{})
	go func() {
		time.Sleep(1 * time.Second)
		done <- struct{}{}
	}()
	// generate data
	go func() {
		for i := 0; i < 10; i++ {
			myChan <- i
		}
	}()
	for val := range orDone(done, myChan) {
		fmt.Println(val)
	}

}
